using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using mock_ehr_lib.Data;
using System.Xml;
using System.Xml.XPath;
using mock_ehr_lib.Data.LookupServices;

namespace mock_ehr_lib.Model.Summary
{
    public class PatientSummary
    {
        // the following tool was helpful in deriving these xpaths:
        // http://www.bit-101.com/xpath/

        // this is helpful for implementation:
        // http://wiki.hitsp.org/docs/C83/C83-3.html

        public PatientSummary()
        {
            
        }

        public int ID { get; set; }
        public string GivenName { get; set; }
        public string FamilyName { get; set; }
        public DateTime? DOB { get; set; }
        public string Gender { get; set; }

        public IEnumerable<ProblemItem> Problems { get; set; }
        public IEnumerable<FamilyHistoryItem> FamilyHistory { get; set; }
        public IEnumerable<SocialHistoryItem> SocialHistory { get; set; }
        public IEnumerable<AlertItem> Alerts { get; set; }
        public IEnumerable<ImmunizationItem> Immunizations { get; set; }

        public static PatientSummary FromCCR(ContinuityOfCareRecord ccr)
        {
            var patientSummary = new PatientSummary();

            // Load problems
            var problemItems = new List<ProblemItem>();
            foreach(var problem in ccr.Body.Problems)
            {
                var problemItem = new ProblemItem();
                var codeType = problem.Description.Code.FirstOrDefault();
                var description = "";
                // TODO 
                // lookupService = LookupServiceFactory.Create(codingSystem)
                // lookupService.GetDescriptionByCode(code)
                if(codeType != null)
                {
                    switch(codeType.CodingSystem)
                    {
                        case "ICD9":
                            
                            description = ICD9LookupService.Instance.GetDescriptionByCode(codeType.Value);
                            break;
                        default:
                            break;
                    }
                    problemItem.Description = description;
                }
                problemItem.Description = description;
                problemItem.StartDate = DateTime.Parse(problem.DateTime.Where(i => i.Type.Text == "Start date").FirstOrDefault().ExactDateTime);
                problemItem.EndDate = DateTime.Parse(problem.DateTime.Where(i => i.Type.Text == "Stop date").FirstOrDefault().ExactDateTime);
            }
            // Load allergies
            var allergyItems = new List<AlertItem>();
            foreach(var alert in ccr.Body.Alerts)
            {
                
                var codeType = alert.Description.Code.FirstOrDefault();
                var description = "";
                if(codeType != null)
                {
                    switch(codeType.CodingSystem)
                    {
                        case "FDB":
                        case "NDC":
                            // NDC lookups; maybe dailymed?
                            break;
                        default:
                            break;
                    }
                }
            }
            // Load family history
            var familyHistoryItems = new List<FamilyHistoryItem>();
            foreach(var familyHistory in ccr.Body.FamilyHistory)
            {
                var familyHistoryItem = new FamilyHistoryItem();
                foreach (var familyMember in familyHistory.FamilyMember)
                {
                    var member = familyMember;
                    var actor = ccr.Actors.Where(i => i.ActorObjectID == member.ActorID).FirstOrDefault();
                }
                familyHistoryItems.Add(familyHistoryItem);
            }
            // Load social history
            var socialHistoryItems = new List<SocialHistoryItem>();
            foreach(var socialHistory in ccr.Body.SocialHistory)
            {
                var socialHistoryItem = new SocialHistoryItem();
                
            }
            // Load results
            var resultItems = new List<ResultItem>();
            foreach(var result in ccr.Body.Results)
            {
                
            }
            return patientSummary;
        }

        public static PatientSummary FromCCDXml(XmlDocument ccdXml)
        {           
            var patientSummary = new PatientSummary();
            var namespaceManager = new XmlNamespaceManager(ccdXml.NameTable);
            namespaceManager.AddNamespace("ns", "urn:hl7-org:v3");
            // given name
            var givenNameXPath = "//ns:patient/ns:name/ns:given";
            var givenNameNode = ccdXml.SelectSingleNode(givenNameXPath, namespaceManager);
            if(givenNameNode != null)
            {
                patientSummary.GivenName = givenNameNode.InnerText;
            }
            // family name
            var familyNameXPath = "//ns:patient/ns:name/ns:family";
            var familyNameNode = ccdXml.SelectSingleNode(familyNameXPath, namespaceManager);
            if (familyNameNode != null)
            {
                patientSummary.FamilyName = familyNameNode.InnerText;
            }
            // dob
            var birthTimeXPath = "//ns:patient/ns:birthTime/@value";
            var birthTimeNode = ccdXml.SelectSingleNode(birthTimeXPath, namespaceManager);
            if(birthTimeNode != null)
            {
                var birthTimeValue = birthTimeNode.Value;
                var year = birthTimeValue.Substring(0, 4);
                var month = birthTimeValue.Length >= 6 ? birthTimeValue.Substring(4, 2) : "1";
                var day = birthTimeValue.Length >= 8 ? birthTimeValue.Substring(6, 2) : "1"; ;
                patientSummary.DOB = DateTime.Parse(string.Format("{0}/{1}/{2}", month, day, year));
            }
            // gender
            var genderXPath = "//ns:patient/ns:administrativeGenderCode[@codeSystem='2.16.840.1.113883.5.1']/@code";
            var genderNode = ccdXml.SelectSingleNode(genderXPath, namespaceManager);
            if (genderNode != null)
            {
                patientSummary.Gender = genderNode.Value;
            }
            patientSummary.FamilyHistory = FamilyHistoryItem.FromCCD(ccdXml, namespaceManager);
            patientSummary.SocialHistory = SocialHistoryItem.FromCCD(ccdXml, namespaceManager);
            patientSummary.Problems = ProblemItem.FromCCD(ccdXml, namespaceManager);
            patientSummary.Alerts = AlertItem.FromCCD(ccdXml, namespaceManager);
            patientSummary.Immunizations = ImmunizationItem.FromCCD(ccdXml, namespaceManager);
            return patientSummary;
        }
    }
}